﻿namespace IBTrader.Indicator.Oscillator
{
    using IBTrader.Modules.Read;
    using IBTrader.Charts;
    using System;

    /// <summary>
    /// The Stochastic Oscillator "doesn't follow price, it doesn't follow volume or anything like that.
    /// It follows the speed or the momentum of price. As a rule, the momentum changes direction before price.
    /// As such, bullish and bearish divergences in the Stochastic Oscillator can be used to foreshadow reversals.
    /// Because the Stochastic Oscillator is range bound, is also useful for identifying overbought and oversold levels.
    /// </summary>
    class Stochastic : BasePrices
    {
        internal virtual event EventHandler<Line> HitK, HitKD, HitD;
        private readonly Prices Ks, KDs;
        public Stochastic(Worker worker, int K = 14, int KD = 3, int D = 3) : base(worker, new ChartArgs { Group = 1 }, K) { Ks = new Prices(KD); KDs = new Prices(D); }
        public override void Add(object _, Line line)
        {
            Prices.Add(line.Price);

            Ks.Add(NaN(Relative(Prices) * 100));
            OnHit(HitK, ChartArgs.EventType.HitK, line, Ks.Last());

            KDs.Add(NaN(Ks.Average()));
            OnHit(HitKD, ChartArgs.EventType.HitKD, line, KDs.Last());

            var d = NaN(KDs.Average());
            OnHit(HitD, ChartArgs.EventType.HitD, line, d);
            OnHit(line, d);
        }
        internal static double Relative(Prices prices)
        {
            var min = prices.Min();
            return (prices.Last() - min) / (prices.Max() - min);
        }
    }
}